import { BadRequestException, Injectable } from '@nestjs/common';
import { CreatePublicResourceDto } from './dto/create-public_resource.dto';
import * as path from 'path';
import * as fs from 'fs';
import { promises as fsPromises } from 'fs';
import { ImagerasterService } from 'src/imageraster/imageraster.service';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { PublicResource } from './entities/public_resource.entity';
import { request, type Response } from 'express';
import { FileUtil } from 'src/common/file';
import { UpdatePublicResourceDto } from './dto/update-public_resource.dto';

@Injectable()
export class PublicResourceService {
  constructor(
    @InjectRepository(PublicResource)
    private readonly publicResourceRepository: Repository<PublicResource>,
    private readonly imagerasterService: ImagerasterService,
  ) {}
  async createPublicResourceItem(
    createPublicResourceDto: CreatePublicResourceDto,
    file: Express.Multer.File,
  ) {
    if (file.mimetype === 'image/tiff') {
      const file_path = path.resolve(
        `${process.env.FILE_PATH}/public/imageraster/${file.filename}`,
      );
      const output_path = path.resolve(
        `${
          process.env.FILE_PATH
        }/public/imagerasterTopng/${file.filename.replace('.tif', '.png')}`,
      );
      const destinationPath = path.resolve(
        `${process.env.FILE_PATH}/public/imagerasterTopng`,
      );
      if (!fs.existsSync(destinationPath)) {
        fs.mkdirSync(destinationPath, { recursive: true });
      }
      await this.imagerasterService.tif2png(file_path, output_path);
    }
    createPublicResourceDto.file_name = file.filename;
    createPublicResourceDto.src = file.filename;
    createPublicResourceDto.original_name = Buffer.from(
      file.originalname,
      'latin1',
    ).toString('utf8');
    createPublicResourceDto.size = String(file.size);
    createPublicResourceDto.raw_type = file.mimetype;
    createPublicResourceDto.folder = '-1';
    const insertRes = await this.publicResourceRepository.insert(
      this.publicResourceRepository.create(createPublicResourceDto),
    );
    return (insertRes.raw[0] as any).id;
  }

  async deletePublicResourceById(id: string) {
    // 执行删除逻辑
    const fileItem = await this.publicResourceRepository.findOne({
      where: { id: id },
    });
    try {
      const result = await this.publicResourceRepository.delete({ id: id });
      // 判断
      const fileList = await this.publicResourceRepository.find({
        where: {
          src: fileItem.src,
        },
      });
      if (fileList.length === 0) {
        let folder = 'other'; // 默认文件夹名
        if (fileItem.raw_type.startsWith('image/')) {
          if (fileItem.raw_type === 'image/tiff') {
            folder = 'imageraster';
          } else {
            folder = 'image';
          }
        } else if (fileItem.raw_type.startsWith('audio/')) {
          folder = 'audio';
        } else if (fileItem.raw_type.startsWith('video/')) {
          folder = 'video';
        } else if (fileItem.raw_type.startsWith('text/')) {
          folder = 'text';
        } else if (fileItem.raw_type.startsWith('application/')) {
          folder = 'application';
        }
        const fileName = path.resolve(
          process.env.FILE_PATH +
            '/' +
            'public' +
            '/' +
            folder +
            '/' +
            fileItem.src,
        );
        if (result.affected && result.affected > 0) {
          await FileUtil.deleteLocalFile(fileName);
          if (folder === 'imageraster') {
            const imagerasterPath = path.resolve(
              `${process.env.FILE_PATH}/${
                fileItem.uploader
              }/imagerasterTopng/${fileItem.src.replace('.tif', '.png')}`,
            );
            await FileUtil.deleteLocalFile(imagerasterPath);
          }
          return `成功删除 ${result.affected} 条记录`;
        } else {
          return `未找到匹配的记录，没有进行删除操作`;
        }
      }
    } catch (err) {
      console.error('删除记录失败', err);
      throw '删除记录失败';
    }
  }
  getPublicResourceById(id: string) {
    return this.publicResourceRepository.findOne({ where: { id: id } });
  }
  getAllPublicResource() {
    return this.publicResourceRepository.find();
  }

  async getFileItemContent(id: string, response: Response) {
    const res = await this.publicResourceRepository.findOne({
      where: { id: id },
    });
    if (res) {
      let folder = '';
      if (res.raw_type.startsWith('image/')) {
        if (res.raw_type === 'image/tiff') {
          folder = 'imagerasterTopng';
          res.raw_type = 'image/png';
        } else {
          folder = 'image';
        }
      } else if (res.raw_type.startsWith('audio/')) {
        folder = 'audio';
      } else if (res.raw_type.startsWith('video/')) {
        folder = 'video';
      } else if (res.raw_type.startsWith('text/')) {
        folder = 'text';
      } else if (res.raw_type.startsWith('application/')) {
        folder = 'application';
      }
      const destinationPath = path.resolve(
        `${process.env.FILE_PATH}/public/${folder}/${res.src.replace(
          '.tif',
          '.png',
        )}`,
      );
      const stats = await fsPromises.stat(destinationPath);
      response.setHeader('Content-Type', res.raw_type);
      response.setHeader('Content-Length', stats.size.toString());
      response.setHeader('Accept-Ranges', 'bytes');

      const fileStream = fs.createReadStream(destinationPath);
      fileStream.pipe(response);
    }
  }

  async downloadPublicResourceItemStream(id: string, response: Response) {
    try {
      const res = await this.publicResourceRepository.findOne({
        where: { id: id },
      });
      if (!res) {
        throw new Error('File not found');
      }

      let folder = 'other';
      if (res.raw_type.startsWith('image/')) {
        folder = res.raw_type === 'image/tiff' ? 'imageraster' : 'image';
      } else if (res.raw_type.startsWith('audio/')) {
        folder = 'audio';
      } else if (res.raw_type.startsWith('video/')) {
        folder = 'video';
      } else if (res.raw_type.startsWith('text/')) {
        folder = 'text';
      } else if (res.raw_type.startsWith('application/')) {
        folder = 'application';
      }

      const filePath = path.resolve(
        `${process.env.FILE_PATH}/public/${folder}/${res.src}`,
      );

      // Set appropriate headers
      response.setHeader('Content-Type', res.raw_type);
      response.setHeader(
        'Content-Disposition',
        `attachment; filename="${encodeURIComponent(res.src)}"`,
      );

      // Stream the file directly
      const fileStream = fs.createReadStream(filePath);
      fileStream.pipe(response);
    } catch (err) {
      console.error('下载记录失败', err);
      response.status(500).send('下载记录失败');
    }
  }

  async updatePublicResourceById(
    id: string,
    updatePublicResourceDto: UpdatePublicResourceDto,
  ) {
    const oldFile = await this.publicResourceRepository.findOne({
      where: { id: id },
    });
    if (!oldFile) {
      return '未找到匹配的记录，没有进行更新操作';
    }
    try {
      const updateFlie = this.publicResourceRepository.merge(
        oldFile,
        updatePublicResourceDto,
      );
      await this.publicResourceRepository.save(updateFlie);
      return '修改文件属性成功!';
    } catch (err) {
      throw new BadRequestException('更新文件条目失败');
    }
  }

  getPublicResourcPicture() {
    return this.publicResourceRepository
      .createQueryBuilder('publicResource_list')
      .where('publicResource_list.raw_type LIKE :prefix', {
        prefix: 'image/%',
      })
      .andWhere('publicResource_list.raw_type NOT LIKE :excludeType', {
        excludeType: 'image/tiff',
      })
      .getMany();
  }
  getPublicResourcVideo() {
    return this.publicResourceRepository
      .createQueryBuilder('publicResource_list')
      .where('publicResource_list.raw_type LIKE :prefix', {
        prefix: 'video/%',
      })
      .getMany();
  }
  getPublicResourcAudio() {
    return this.publicResourceRepository
      .createQueryBuilder('publicResource_list')
      .where('publicResource_list.raw_type LIKE :prefix', { prefix: 'audio/%' })
      .getMany();
  }
  getPublicResourcGeojson() {
    return this.publicResourceRepository
      .createQueryBuilder('publicResource_list')
      .where('publicResource_list.raw_type = :upload', {
        upload: 'application/json',
      })
      .getMany();
  }
  getPublicResourcRaster() {
    return this.publicResourceRepository
      .createQueryBuilder('publicResource_list')
      .where('publicResource_list.raw_type = :upload', { upload: 'image/tiff' })
      .getMany();
  }
}
